#include <hash.h>
#include "filesys/file.h"
#include "devices/block.h"
#include "threads/synch.h"

/* Defines position of a frame */
#define FRAME_IN_MEM 0
#define FRAME_ON_DISK 1
#define FRAME_ON_SWAP 2

/* Defines property of a frame */
#define READONLY 0
#define READWRITE 1

/* Defines type of file */
#define EXECUTABLE_FILE 0
#define PROCESS_STACK 1
#define MMAP_FILE 2


// struct FRAME 

struct frame_struct
{
  int pos_flag;		// defines the position of frame
  int property_flag;		// defines the property of this frame
  int type_flag; 		// defines the frame type
  bool is_all_zeroes;		// true, if the page is of zero size
  uint8_t *upage;		// stores the user addres 
  uint8_t *vaddr;		// stores the virtual address, if frame in memory
  size_t len;			// stores the length of the page
  struct thread *t;		// pointer to the thread that created this frame
  block_sector_t sector_num;	// defines sector # if frame is on disk/swap
  struct list_elem elem;	// List element
  struct lock frame_lock;	// to be acquired before using this frame
};

// strcut PAGE
struct page_struct
{
  int key;			// defines the key for HASH table
  struct frame_struct *frame;	// stores pointer to the mapped FRAME
  struct hash_elem elem;	// hash element
};

void initialize_frame_tables ();
bool allocate_page (int, int, int, bool, uint8_t *, uint8_t *, 
	            size_t, block_sector_t);
void deallocate_page (uint8_t *);
struct page_struct *supp_page_table_lookup (uint32_t *);
uint32_t* page_table_entry_lookup (uint8_t *, uint32_t *, bool);
uint8_t *evict_frame ();
void free_ps (struct page_struct *);
